﻿#Include ..\..\_lib\ScrollGui.ahk


class OutputGui {

  static maxLen := 30, lineH := 21

  __New(parent) {
    this.maxH := maxMsg * OutputGui.lineH - 2
    g := Gui()
    g.BackColor := 'F4FAFE'
    g.SetFont('s12', 'consolas')
    g.AddText('w300 h' this.maxH ' x0 y0')
    g.MarginX := g.MarginY := 0
    sg := ScrollGUI(g.Hwnd, 0, 0, '-Caption -Resize', 2, 2)
    ; sg.SetLine(2, 22)
    sg.container.Opt('+Parent' parent)

    DllCall('SetParent', 'ptr', sg.container.Hwnd, 'ptr', parent)
    this.sg := sg, this.child := g
    this.h := 0, this._h := 0
  }

  Show(x, y, options) {
    this.sg.Show('', Format('x{} y{} {}', x, y, options))
    this._HideScrollBar()
  }

  Hide() {
    this.sg.container.Hide()
  }

  Resume() {
    this.sg.container.Restore()
  }

  _HideScrollBar() {
    WinSetRegion('0-0 w300 h' this.maxH, this.sg.container)
  }

  _ShowScrollBar() {
    WinSetRegion(, this.sg.container)
  }

  ScrollToTop() {
    while this.sg.PosV > 1
      SendMessage(0x0115, 2, 0, this.sg.container)
  }

  ScrollToBottom() {
    while this.sg.MaxV - this.sg.PageV + 1 > this.sg.PosV
      SendMessage(0x0115, 3, 0, this.sg.container)
  }

  OnCopy(g, *) {
    if !g['raw']
      return
    A_Clipboard := g['raw']
    Tip.ShowTip('copied!', Cursor.x + 10, Cursor.y + 10, 2000)
  }

  Destroy() {
    this.sg.Destroy()
  }

  Add(text, isInput := false, succ := true, async := false, options := {}) {
    t := slice(text, OutputGui.maxLen - 1)
    tb := this.child.AddText('x0 w27 y' this._h ' Background' (isInput ? 'b6e8b6' : succ ? 'b4d4e1' : 'e8bfbf')
      , (async ? '~> ' : isInput ? '<< ' : succ ? '>> ' : '>| ') . '`n---'.repeat(t.count('`n')))
    ta := this.child.AddText(options['align'] ' Background' Ternary(options['b2'], 'D2E6F1') ' w271 x+2 ', t)

    ta.OnEvent('ContextMenu', (v, *) => this.OnCopy(v)), ta.GetPos(, &y, , &h)
    ta.raw := text
    this._h += h + 2
    if this._h > this.maxH
      this._ShowScrollBar()
    this.h := min(this.h + h + 2, this.maxH)
    D this.h
    this.sg.AdjustToChild()
    this.ScrollToBottom()

    ta.Redraw(), tb.Redraw()
    return h
  }

}